// Copyright (c) Appeon. All rights reserved.
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. 
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0.

namespace SnapObjects.Data
{
    /// <summary>
    ///     Represents an object which can be used to create a joined table in the FROM clause. Joins the original 
    ///     table source with a new table source by the specified JOIN operation. A joined table is a result set 
    ///     that combines two or more tables.
    /// </summary>
    public interface ISqlJoinBuilder : ISqlWhereBuilder
    {
        /// <summary>
        ///     Creates a table by joining the original table source with a new table source, without specifying the 
        ///     type of the JOIN operator. You need to specify a schema and an alias for the new table source.
        /// </summary>
        /// <param name="table">The name of the new table source.</param>
        /// <returns>
        ///     Returns an ISqlJoinOnBuilder object which can be used to create the condition on which the join is based.
        /// </returns>
        ISqlJoinOnBuilder Join(string table);

        /// <summary>
        ///     Creates a table by joining the original table source with a new table source, without specifying the 
        ///     type of the JOIN operator. You need to specify a schema and an alias for the new table source.
        /// </summary>
        /// <param name="table">The name of the new table source.</param>
        /// <param name="alias">The alias of the new table source.</param>
        /// <returns>
        ///     Returns an ISqlJoinOnBuilder object which can be used to create the condition on which the join is based.
        /// </returns>
        ISqlJoinOnBuilder Join(string table, string alias);

        /// <summary>
        ///     Creates a table by joining the original table source with a new table source, without specifying the 
        ///     type of the JOIN operator. You need to specify a schema and an alias for the new table source.
        /// </summary>
        /// <param name="table">The name of the new table source.</param>
        /// <param name="alias">The alias of the new table source.</param>
        /// <param name="schema">The schema of the new table source.</param>
        /// <returns>
        ///     Returns an ISqlJoinOnBuilder object which can be used to create the condition on which the join is based.
        /// </returns>
        ISqlJoinOnBuilder Join(string table, string alias, string schema);

        /// <summary>
        ///     Uses the INNER JOIN operator to join the original table source directly with a raw SQL. 
        ///     You need to specify an alias for the raw SQL.
        /// </summary>
        /// <param name="joinClause">A string of raw SQL after the JOIN keyword.</param>
        /// <returns>
        ///     Returns an ISqlJoinOnBuilder object which can be used to create the condition on which the join is based.
        /// </returns>
        ISqlJoinOnBuilder JoinRaw(string joinClause);

        /// <summary>
        ///     Uses the INNER JOIN operator to join the original table source directly with a raw SQL. 
        ///     You need to specify an alias for the raw SQL.
        /// </summary>
        /// <param name="joinClause">A string of raw SQL after the JOIN keyword.</param>
        /// <param name="builderAlias">The alias for the raw SQL.</param>
        /// <returns>
        ///     Returns an ISqlJoinOnBuilder object which can be used to create the condition on which the join is based.
        /// </returns>
        ISqlJoinOnBuilder JoinRaw(string joinClause, string builderAlias);

        /// <summary>
        ///     Creates a table by joining the original table source with a new table source which is specified by a 
        ///     subquery generated by an ISqlBuilder object. You need to specify an alias for the new table source.
        /// </summary>
        /// <param name="sqlBuilder">An ISqlBuilder object which represents a subquery.</param>
        /// <param name="alias">The alias of the new table source specified by the sqlBuilder parameter.</param>
        /// <returns>
        ///     Returns an ISqlJoinOnBuilder object which can be used to create the condition on which the join is based.
        /// </returns>
        ISqlJoinOnBuilder Join(ISqlBuilder sqlBuilder, string alias);

        /// <summary>
        ///     Uses the INNER JOIN operator to join the original table source and the new table source to create a joined table. 
        ///     You need to specify a schema and an alias for the new table source.
        /// </summary>
        /// <param name="table">The name of the new table source.</param>
        /// <returns>
        ///     Returns an ISqlJoinOnBuilder object which can be used to create the condition on which the join is based.
        /// </returns>
        ISqlJoinOnBuilder InnerJoin(string table);

        /// <summary>
        ///     Uses the INNER JOIN operator to join the original table source and the new table source to create a joined table. 
        ///     You need to specify a schema and an alias for the new table source.
        /// </summary>
        /// <param name="table">The name of the new table source.</param>
        /// <param name="alias">The alias of the new table source.</param>
        /// <returns>
        ///     Returns an ISqlJoinOnBuilder object which can be used to create the condition on which the join is based.
        /// </returns>
        ISqlJoinOnBuilder InnerJoin(string table, string alias);

        /// <summary>
        ///     Uses the INNER JOIN operator to join the original table source and the new table source to create a joined table. 
        ///     You need to specify a schema and an alias for the new table source.
        /// </summary>
        /// <param name="table">The name of the new table source.</param>
        /// <param name="alias">The alias of the new table source.</param>
        /// <param name="schema">The schema of the new table source.</param>
        /// <returns>
        ///     Returns an ISqlJoinOnBuilder object which can be used to create the condition on which the join is based.
        /// </returns>
        ISqlJoinOnBuilder InnerJoin(string table, string alias, string schema);

        /// <summary>
        ///     Uses the INNER JOIN operator to join the original table source directly with a raw SQL to create a joined table. 
        ///     You need to specify an alias for the raw SQL.
        /// </summary>
        /// <param name="joinClause">A string of raw SQL after the INNER JOIN keyword.</param>
        /// <returns>
        ///     Returns an ISqlJoinOnBuilder object which can be used to create the condition on which the join is based.
        /// </returns>
        ISqlJoinOnBuilder InnerJoinRaw(string joinClause);

        /// <summary>
        ///     Uses the INNER JOIN operator to join the original table source directly with a raw SQL to create a joined table. 
        ///     You need to specify an alias for the raw SQL.
        /// </summary>
        /// <param name="joinClause">A string of raw SQL after the INNER JOIN keyword.</param>
        /// <param name="builderAlias">The alias for the raw SQL.</param>
        /// <returns>
        ///     Returns an ISqlJoinOnBuilder object which can be used to create the condition on which the join is based.
        /// </returns>
        ISqlJoinOnBuilder InnerJoinRaw(string joinClause, string builderAlias);

        /// <summary>
        ///     Uses the INNER JOIN operator to join the original table source and the new table source (specified by a subquery
        ///     generated by an ISqlBuilder object) to create a joined table. You need to specify an alias for the new table source.
        /// </summary>
        /// <param name="sqlBuilder">An ISqlBuilder object which represents a subquery.</param>
        /// <param name="alias">The alias of the new table source specified by the sqlBuilder parameter.</param>
        /// <returns>
        ///     Returns an ISqlJoinOnBuilder object which can be used to create the condition on which the join is based.
        /// </returns>
        ISqlJoinOnBuilder InnerJoin(ISqlBuilder sqlBuilder, string alias);

        /// <summary>
        ///     Uses the LEFT OUTER JOIN operator to join the original table source and the new table source to create a joined table. 
        ///     You need to specify a schema and an alias for the new table source.
        /// </summary>
        /// <param name="table">The name of the new table source.</param>
        /// <returns>
        ///     Returns an ISqlJoinOnBuilder object which can be used to create the condition on which the join is based.
        /// </returns>
        ISqlJoinOnBuilder LeftJoin(string table);

        /// <summary>
        ///     Uses the LEFT OUTER JOIN operator to join the original table source and the new table source to create a joined table. 
        ///     You need to specify a schema and an alias for the new table source.
        /// </summary>
        /// <param name="table">The name of the new table source.</param>
        /// <param name="alias">The alias of the new table source.</param>
        /// <returns>
        ///     Returns an ISqlJoinOnBuilder object which can be used to create the condition on which the join is based.
        /// </returns>
        ISqlJoinOnBuilder LeftJoin(string table, string alias);

        /// <summary>
        ///     Uses the LEFT OUTER JOIN operator to join the original table source and the new table source to create a joined table. 
        ///     You need to specify a schema and an alias for the new table source.
        /// </summary>
        /// <param name="table">The name of the new table source.</param>
        /// <param name="alias">The alias of the new table source.</param>
        /// <param name="schema">The schema of the new table source.</param>
        /// <returns>
        ///     Returns an ISqlJoinOnBuilder object which can be used to create the condition on which the join is based.
        /// </returns>
        ISqlJoinOnBuilder LeftJoin(string table, string alias, string schema);

        /// <summary>
        ///     Uses the LEFT OUTER JOIN operator to join the original table source directly with a raw SQL to create 
        ///     a joined table. You need to specify an alias for the raw SQL.
        /// </summary>
        /// <param name="joinClause">A string of raw SQL after the LEFT OUTER JOIN keyword.</param>
        /// <returns>
        ///     Returns an ISqlJoinOnBuilder object that can be used to create the condition on which the join is based.
        /// </returns>
        ISqlJoinOnBuilder LeftJoinRaw(string joinClause);

        /// <summary>
        ///     Uses the LEFT OUTER JOIN operator to join the original table source directly with a raw SQL to create 
        ///     a joined table. You need to specify an alias for the raw SQL.
        /// </summary>
        /// <param name="joinClause">A string of raw SQL after the LEFT OUTER JOIN keyword.</param>
        /// <param name="builderAlias">The alias for the raw SQL.</param>
        /// <returns>
        ///     Returns an ISqlJoinOnBuilder object that can be used to create the condition on which the join is based.
        /// </returns>
        ISqlJoinOnBuilder LeftJoinRaw(string joinClause, string builderAlias);

        /// <summary>
        ///     Uses the LEFT OUTER JOIN operator to join the original table source and the new table source 
        ///     (specified by a subquery generated by an ISqlBuilder object) to create a joined table. 
        ///     You need to specify an alias for the new table source.
        /// </summary>
        /// <param name="sqlBuilder">An ISqlBuilder object which represents a subquery.</param>
        /// <param name="alias">The alias of the new table source specified by the sqlBuilder parameter.</param>
        /// <returns>
        ///     Returns an ISqlJoinOnBuilder object that can be used to create the condition on which the join is based.
        /// </returns>
        ISqlJoinOnBuilder LeftJoin(ISqlBuilder sqlBuilder, string alias);

        /// <summary>
        ///     Creates a table by joining the original table source with a new table source using the RIGHT OUTER JOIN operator. 
        ///     You need to specify a schema and an alias for the new table source.
        /// </summary>
        /// <param name="table">The name of the new table source.</param>
        /// <returns>
        ///     Returns an ISqlJoinOnBuilder object which can be used to create the condition on which the join is based.
        /// </returns>
        ISqlJoinOnBuilder RightJoin(string table);

        /// <summary>
        ///     Creates a table by joining the original table source with a new table source using the RIGHT OUTER JOIN operator. 
        ///     You need to specify a schema and an alias for the new table source.
        /// </summary>
        /// <param name="table">The name of the new table source.</param>
        /// <param name="alias">The alias of the new table source.</param>
        /// <returns>
        ///     Returns an ISqlJoinOnBuilder object which can be used to create the condition on which the join is based.
        /// </returns>
        ISqlJoinOnBuilder RightJoin(string table, string alias);

        /// <summary>
        ///     Creates a table by joining the original table source with a new table source using the RIGHT OUTER JOIN operator. 
        ///     You need to specify a schema and an alias for the new table source.
        /// </summary>
        /// <param name="table">The name of the new table source.</param>
        /// <param name="alias">The alias of the new table source.</param>
        /// <param name="schema">The schema of the new table source.</param>
        /// <returns>
        ///     Returns an ISqlJoinOnBuilder object which can be used to create the condition on which the join is based.
        /// </returns>
        ISqlJoinOnBuilder RightJoin(string table, string alias, string schema);

        /// <summary>
        ///     Uses the RIGHT OUTER JOIN operator to join the original table source directly with a string of raw SQL to 
        ///     create a joined table. You need to specify an alias for the raw SQL.
        /// </summary>
        /// <param name="joinClause">A string of raw SQL following the RIGHT OUTER JOIN operator.</param>
        /// <returns>
        ///     Returns an ISqlJoinOnBuilder object which can be used to create the condition on which the join is based.
        /// </returns>
        ISqlJoinOnBuilder RightJoinRaw(string joinClause);

        /// <summary>
        ///     Uses the RIGHT OUTER JOIN operator to join the original table source directly with a string of raw SQL to 
        ///     create a joined table. You need to specify an alias for the raw SQL.
        /// </summary>
        /// <param name="joinClause">A string of raw SQL following the RIGHT OUTER JOIN operator.</param>
        /// <param name="builderAlias">The alias for the raw SQL.</param>
        /// <returns>
        ///     Returns an ISqlJoinOnBuilder object which can be used to create the condition on which the join is based.
        /// </returns>
        ISqlJoinOnBuilder RightJoinRaw(string joinClause, string builderAlias);

        /// <summary>
        ///     Uses the RIGHT OUTER JOIN operator to join the original table source and the new table source 
        ///     (specified by a subquery generated by an ISqlBuilder object) to create a joined table. 
        ///     You need to specify an alias for the new table source.
        /// </summary>
        /// <param name="sqlBuilder">An ISqlBuilder object which represents a subquery.</param>
        /// <param name="alias">The alias of the new table source specified by the sqlBuilder parameter.</param>
        /// <returns>
        ///     Returns an ISqlJoinOnBuilder object that can be used to create the condition on which the join is based.
        /// </returns>
        ISqlJoinOnBuilder RightJoin(ISqlBuilder sqlBuilder, string alias);

        /// <summary>
        ///     Uses the FULL OUTER JOIN operator to join the original table source and the new table source to create a 
        ///     joined table. You need to specify a schema and an alias for the new table source.
        /// </summary>
        /// <param name="table">The name of the new table source.</param>
        /// <returns>
        ///     Returns an ISqlJoinOnBuilder object which can be used to create the condition on which the join is based.
        /// </returns>
        ISqlJoinOnBuilder FullJoin(string table);

        /// <summary>
        ///     Uses the FULL OUTER JOIN operator to join the original table source and the new table source to create a 
        ///     joined table. You need to specify a schema and an alias for the new table source.
        /// </summary>
        /// <param name="table">The name of the new table source.</param>
        /// <param name="alias">The alias of the new table source.</param>
        /// <returns>
        ///     Returns an ISqlJoinOnBuilder object which can be used to create the condition on which the join is based.
        /// </returns>
        ISqlJoinOnBuilder FullJoin(string table, string alias);

        /// <summary>
        ///     Uses the FULL OUTER JOIN operator to join the original table source and the new table source to create a 
        ///     joined table. You need to specify a schema and an alias for the new table source.
        /// </summary>
        /// <param name="table">The name of the new table source.</param>
        /// <param name="alias">The alias of the new table source.</param>
        /// <param name="schema">The schema of the new table source.</param>
        /// <returns>
        ///     Returns an ISqlJoinOnBuilder object which can be used to create the condition on which the join is based.
        /// </returns>
        ISqlJoinOnBuilder FullJoin(string table, string alias, string schema);

        /// <summary>
        ///     Uses the FULL OUTER JOIN operator to join the original table source directly with a raw SQL to create a joined table. 
        ///     You need to specify an alias for the raw SQL.
        /// </summary>
        /// <param name="joinClause">A string of raw SQL after the FULL OUTER JOIN keyword.</param>
        /// <returns>
        ///     Returns an ISqlJoinOnBuilder object which can be used to create the condition on which the join is based.
        /// </returns>
        ISqlJoinOnBuilder FullJoinRaw(string joinClause);

        /// <summary>
        ///     Uses the FULL OUTER JOIN operator to join the original table source directly with a raw SQL to create a joined table. 
        ///     You need to specify an alias for the raw SQL.
        /// </summary>
        /// <param name="joinClause">A string of raw SQL after the FULL OUTER JOIN keyword.</param>
        /// <param name="builderAlias">The alias for the raw SQL.</param>
        /// <returns>
        ///     Returns an ISqlJoinOnBuilder object which can be used to create the condition on which the join is based.
        /// </returns>
        ISqlJoinOnBuilder FullJoinRaw(string joinClause, string builderAlias);

        /// <summary>
        ///     Uses the FULL OUTER JOIN operator to join the original table source and the new table source 
        ///     (specified by a subquery generated by an ISqlBuilder object) to create a joined table. 
        ///     You need to specify an alias for the new table source.
        /// </summary>
        /// <param name="sqlBuilder">An ISqlBuilder object which represents a subquery.</param>
        /// <param name="alias">The alias of the new table source specified by the sqlBuilder parameter.</param>
        /// <returns>
        ///     Returns an ISqlJoinOnBuilder object which can be used to create the condition on which the join is based.
        /// </returns>
        ISqlJoinOnBuilder FullJoin(ISqlBuilder sqlBuilder, string alias);

        /// <summary>
        ///     Gets whether a joined table has been created.
        /// </summary>
        bool HasJoin { get; }

        /// <summary>
        ///     Gets whether a joined table has been created and the condition on which the join is based has been specified.
        /// </summary>
        bool HasOn { get; }

        /// <summary>
        ///     Gets the type of the JOIN operation for the specified table source.
        /// </summary>
        /// <param name="tableName">
        ///     The name of the table source.
        /// </param>
        /// <returns>
        ///     Returns the value of the SqlJoinType enumerated type of the JOIN operation if a JOIN operation was specified; 
        ///     otherwise, returns null.
        /// </returns>
        SqlJoinType? GetJoinType(string tableName);

        /// <summary>
        ///     Returns an ISqlWhereAndOr object which represents an object used to build the WHERE clause in a SQL statement.
        /// </summary>
        /// <returns>
        ///     Returns the ISqlWhereAndOr object which can be used to build the WHERE clause in a SQL statement (e.g., 
        ///     adding search conditions to the WHERE clause).
        /// </returns>
        ISqlWhereAndOr AsWhere();
    }
}
